package com.ihr360.job.core.step.builder;

import com.ihr360.job.core.Job;
import com.ihr360.job.core.Step;
import com.ihr360.job.core.job.JobParametersExtractor;
import com.ihr360.job.core.job.JobStep;
import com.ihr360.job.core.lanuch.JobLauncher;
import com.ihr360.job.core.lanuch.support.SimpleJobLauncher;
import com.ihr360.job.core.step.StepBuilderHelper;

/**
 * A step builder for {@link JobStep} instances. A job step executes a nested {@link Job} with parameters taken from the
 * parent job or from the step execution.
 *
 * @author Dave Syer
 * @since 2.2
 */
public class JobStepBuilder extends StepBuilderHelper<JobStepBuilder> {
    private Job job;

    private JobLauncher jobLauncher;

    private JobParametersExtractor jobParametersExtractor;
    /**
     * Create a new builder initialized with any properties in the parent. The parent is copied, so it can be re-used.
     *
     * @param parent a parent helper containing common step properties
     */
    public JobStepBuilder(StepBuilderHelper<?> parent) {
        super(parent);
    }

    /**
     * Provide a job to execute during the step.
     *
     * @param job the job to execute
     * @return this for fluent chaining
     */
    public JobStepBuilder job(Job job) {
        this.job = job;
        return this;
    }

    /**
     * Provide a job parameters extractor. Useful for extracting job parameters from the parent step execution context
     * or job parameters.
     *
     * @param jobParametersExtractor the job parameters extractor to use
     * @return this for fluent chaining
     */
    public JobStepBuilder parametersExtractor(JobParametersExtractor jobParametersExtractor) {
        this.jobParametersExtractor = jobParametersExtractor;
        return this;
    }

    /**
     * Build a step from the job provided.
     *
     * @return a new job step
     */
    public Step build() {

        JobStep step = new JobStep();
        step.setName(getName());
        super.enhance(step);
        if (job != null) {
            step.setJob(job);
        }
        if (jobParametersExtractor != null) {
            step.setJobParametersExtractor(jobParametersExtractor);
        }
        if (jobLauncher == null) {
            SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
            jobLauncher.setJobRepository(getJobRepository());
            try {
                jobLauncher.afterPropertiesSet();
            }
            catch (Exception e) {
                throw new StepBuilderException(e);
            }
            this.jobLauncher = jobLauncher;
        }
        step.setJobLauncher(jobLauncher);
        try {
            step.afterPropertiesSet();
        }
        catch (Exception e) {
            throw new StepBuilderException(e);
        }
        return step;

    }
}